<?php
/*
 * @Author       :  　 @祥💥　技术支持
 * @Mail         : shejiz@qq.com
 * @Date         : 2025-07-18 16:30:16
 * @LastEditTime : 2025-07-18 17:09:15
 * @LastEditors  :  　 @祥💥　技术支持
 * @Description  : 
 * @FilePath     : \35dir\tool\douyin.php
 * It's up to you ^_^
 * Copyright (c) 2025 by shejiz@qq.com, All Rights Reserved. 
 */

if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
    header('Content-Type: application/json; charset=utf-8');
    $res = array('code' => 201, 'message' => '非抖音链接');
    $url = explode(' ', $_POST['url']);
    $url = $url['0'];
    if (strpos($url, 'v.douyin.com') == false) {
        echo json_encode($res, 256);
        exit();
    }
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Accept: */*',
        'Accept-Encoding: gzip',
        'Connection: Keep-Alive',
        'User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)'
    ));
    curl_setopt($ch, CURLOPT_HEADER, true);
    curl_setopt($ch, CURLOPT_NOBODY, 1);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $ret = curl_exec($ch);
    curl_close($ch);
    preg_match("/Location: (.*?)\r\n/iU", $ret, $location);
    if (!isset($location[1])) {
        echo json_encode(['code' => 202, 'message' => '请重试'], 256);
        exit();
    }
    $str = dirname($location[1]);
    $itemId = substr($str, strripos($str, 'video') + 6);
    $ch = curl_init('https://www.iesdouyin.com/share/video/' . $itemId);
    curl_setopt($ch, CURLOPT_HEADER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1 Edg/122.0.0.0'));
    if (isset($data)) {
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    }
    curl_setopt($ch, CURLOPT_TIMEOUT, 5000);
    $res = curl_exec($ch);
    $pattern = '/window\._ROUTER_DATA\s*=\s*(.*?)\<\/script>/s';
    preg_match($pattern, $res, $matches);
    if (!empty($matches[1])) {
        $videoInfo = json_decode(trim($matches[1]), true);
        if (isset($videoInfo['loaderData'])) {
            $images = isset($videoInfo['loaderData']['video_(id)/page']['videoInfoRes']['item_list']['0']['images']) ? $videoInfo['loaderData']['video_(id)/page']['videoInfoRes']['item_list']['0']['images'] : [];
            $result = array(
                'aweme_id' => $itemId,
                'author' => $videoInfo['loaderData']['video_(id)/page']['videoInfoRes']['item_list'][0]['author']['nickname'],
                'uid' => $videoInfo['loaderData']['video_(id)/page']['videoInfoRes']['item_list'][0]['author']['unique_id'],
                'avatar' => $videoInfo['loaderData']['video_(id)/page']['videoInfoRes']['item_list'][0]['author']['avatar_medium']['url_list'][0],
                'like' => $videoInfo['loaderData']['video_(id)/page']['videoInfoRes']['item_list'][0]['statistics']['digg_count'],
                'time' => $videoInfo['loaderData']['video_(id)/page']['videoInfoRes']['item_list'][0]["create_time"],
                'title' => $videoInfo['loaderData']['video_(id)/page']['videoInfoRes']['item_list'][0]['desc'],
                'cover' => $videoInfo['loaderData']['video_(id)/page']['videoInfoRes']['item_list'][0]['video']['cover']['url_list'][0],
                'url' => str_replace('playwm', 'play', $videoInfo['loaderData']['video_(id)/page']['videoInfoRes']['item_list'][0]['video']['play_addr']['url_list'][0]),
                'uri' => $videoInfo['loaderData']['video_(id)/page']['videoInfoRes']['item_list'][0]['video']['play_addr']['uri'],
                'mp3_url' => isset($videoInfo['loaderData']['video_(id)/page']['videoInfoRes']['item_list'][0]['video']['play_url']['uri']) ? $videoInfo['loaderData']['video_(id)/page']['videoInfoRes']['item_list'][0]['video']['play_url']['uri'] : '',
                'msg' => '解析成功',
                'code' => 100,
                'data' => $videoInfo,
                'images' => $images
            );
            echo json_encode($result, 256);
            exit();
        }
    }
    echo json_encode(['code' => 201, 'msg' => '解析失败'], 256);
    exit();
}
?>
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>抖音解析</title>
    <meta name="renderer" content="webkit">
    <meta name="referrer" content="never">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <link rel="stylesheet" href="https://cdn.rcku.cn/ajax/libs/layui/2.7.6/css/layui.min.css " media="all">
    <script src="https://cdn.rcku.cn/ajax/libs/layui/2.7.6/layui.min.js " charset="utf-8"></script>
</head>
<style>
    body {
        margin: 10px;
        background: #f2f2f2;
    }

    .main {
        padding: 6px 6px;
        margin: auto;
        background-color: white;
    }

    .tt {
        color: #1aa700;
        font-size: 1.2rem;
        font-weight: 700;
        padding: 8px;
    }

    .center {
        text-align: center;
    }
</style>
<div class="main">
    <blockquote class="layui-elem-quote tt">抖音解析</blockquote>
    <div class="layui-row">
        <div class="layui-col-md12">
            <div class="layui-col-md4">
                <div class="layui-card-body" id="player" style="display: none;">
                    <div class="layui-form-item" style="margin: 0 10px 10px 10px;">
                        <video name="video" id="video" width="100%" controls autoplay loop></video>
                    </div>
                </div>
            </div>
        </div>
        <div class="layui-col-md12">
            <div class="layui-card-body">
                <form class="layui-form layui-form-pane" action="">
                    <div class="layui-form-item layui-form-text">
                        <label class="layui-form-label">输入分享链接</label>
                        <div class="layui-input-block">
                            <textarea name="link" id="link" placeholder="8.28 08/27 gbA:/ l@C.UY 高温来袭时，我在中国凉都——六盘水。 # 六神在手清凉启城 # 六神清凉节# 贵州很值得  https://v.douyin.com/CeiJjKJG/ 复制此链接，打开Dou音搜索，直接观看视频！" class="layui-textarea"></textarea>
                        </div>
                    </div>
                    <input type="text" name="downloadurl" style="display: none;">
                    <input type="text" name="filename" style="display: none;">
                    <div class="layui-form-item center">
                        <button class="layui-btn" lay-submit="" lay-filter="Submit">提交</button>
                        <!-- <button class="layui-btn" lay-submit="" lay-filter="Remove">再来一个</button> -->
                        <button class="layui-btn" lay-submit="" id="download" style="display: none;" lay-filter="Download">下载</button>
                    </div>
                </form>
            </div>
            <div id="Result" style="display: none;">
                <div class="layui-card-header">解析结果</div>
                <div class="layui-card-body">
                    <div class="layui-field-box">
                        <div style="margin-top: 0px;">
                            <p><span class="layui-badge">uri</span>&nbsp;<span id="uri"></span></p>
                            <p><span class="layui-badge">uid</span>&nbsp;<span id="uid"></span></p>
                            <p><span class="layui-badge">author</span>&nbsp;<span id="author"></span></p>
                            <p><span class="layui-badge">create_time</span>&nbsp;<span id="create_time"></span></p>
                            <p><span class="layui-badge">desc</span>&nbsp;<span id="desc"></span></p>
                            <p><span class="layui-badge">images</span>&nbsp;<span id="images"></span></p>
                            <p><span class="layui-badge">url</span>&nbsp;<span id="url"></span></p>
                            <p><span class="layui-badge">mp3_url</span>&nbsp;<span id="mp3_url"></span></p>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
</body>
<script>
    layui.use(['form'], function() {
        var form = layui.form,
            $ = layui.jquery,
            layer = layui.layer;

        form.on('submit(Submit)', function(data) {
            var link = data.field.link;
            if (link.length == 0) {
                layer.alert('请输入您要解析的内容！', {
                    title: '提示'
                })
                return false;
            }
            var i = link.lastIndexOf("https://");
            i = i === -1 ? link.lastIndexOf("http://") : i;
            var url = link.substr(i);
            var index = layer.load(0, {
                shade: false
            });
            $.ajax({
                type: 'post',
                url: '',
                data: {
                    url: url
                },
                success: function(s) {
                    if (s.code == 100) {
                        var videourl = s.url;
                        $('#desc').html(s.title);
                        $('#title').html(s.title);
                        $('#author').html(s.author);
                        $('#uid').html(s.uid);
                        $('#uri').html(s.uri);
                        $('#Result').show();
                        $('#vice').show();
                        $('#video').attr('src', videourl);
                        $('#player').show();
                        $('#link').val('');
                        $('#url').html(s.url);
                        $('#mp3_url').html(s.mp3_url);
                        $("input[name=downloadurl]").val(videourl);
                        $("input[name=filename]").val(s.time + '.mp4');

                        if (s.images.length > 0) {
                            for (var i = 0; i < s.images.length; i++) {
                                $('#images').append('<img src="' + s.images[i]['url_list'][0] + '" style="width:200px;height:auto;padding:5px;">');
                            }
                        }
                    }
                    layer.msg(s.msg);
                    layer.close(index);
                }
            });
            return false;
        });
        form.on('submit(Remove)', function(data) {
            $("#Result").hide();
            $("#link").val('');
            $('#video').attr('src', '');
            $('#download').hide();
            $('#player').hide();
            $('#vice').hide();
            return false;
        });
        form.on('submit(Download)', function(data) {
            downloadBlobFile('get', data.field.downloadurl).onreadystatechange = res => {
                if (res.currentTarget.readyState == 4 && res.currentTarget.status == 200) {
                    const url = window.URL.createObjectURL(res.currentTarget.response);
                    let a = document.createElement('a');
                    a.href = url;
                    a.download = data.field.filename;
                    a.click();
                }
            }
            return false;
        });

        $('#Go .layui-btn').on('click', function() {
            var othis = $(this),
                method = othis.data('method');
            $.ajax({
                type: 'post',
                url: '',
                data: {
                    t: method
                },
                success: function(s) {
                    layer.msg(s.mess, {
                        icon: 1
                    });
                    if (s.code == 200) {
                        setTimeout(function() {
                            location.reload();
                        }, 1000);
                    }
                }
            });
        });
    });

    function downloadBlobFile(_method, _url) {
        const request = new XMLHttpRequest();
        request.open(_method, _url);
        request.send();
        request.responseType = 'blob';
        return request;
    }
</script>
</body>

</html>